package hn.cch.framework.util;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Vector;

public class SftpUtil {

    private static Logger logger = LoggerFactory.getLogger(SftpUtil.class);


    /**
     * 连接sftp
     *
     * @param host
     * @param port
     * @param username
     * @param password
     * @return
     */
    public static ChannelSftp connectSftp(String host, int port, String username, String password) {
        JSch jsch = new JSch();
        Session session = null;
        Channel channel = null;
        try {
            session = jsch.getSession(username, host, port);
            session.setPassword(password);

            Properties properties = new Properties();
            properties.put("StrictHostKeyChecking", "no");
            session.setConfig(properties);
            session.connect();
            logger.info("ServerVersion={}", session.getServerVersion());
            channel = session.openChannel("sftp");
            channel.connect();
            ChannelSftp channelSftp = (ChannelSftp) channel;
            logger.info("sftp.pwd={}", channelSftp.pwd());
            return channelSftp;
        } catch (JSchException | SftpException e) {
            logger.error("connectSftp exception : ", e.getMessage());
            return null;
        }
    }


    /**
     * 断开sftp
     *
     * @param session
     * @param channel
     */
    public static void disconnectSftp(Session session, Channel channel) {
        if (channel != null) {
            channel.disconnect();
        }
        if (session != null) {
            session.disconnect();
        }


    }

    /**
     * 下载文件：先判断文件是否存在
     *
     * @param channelSftp
     * @param remoteFile
     * @return
     */
    public static InputStream downloadFile(ChannelSftp channelSftp, String remoteFile) {

        if (!fileExists(channelSftp, remoteFile)) {
            logger.error("sftp file isnot exist");
            return null;
        }

        String remotePath = remoteFile.substring(0, remoteFile.lastIndexOf("/"));
        String remoteName = remoteFile.substring(remoteFile.lastIndexOf("/") + 1);
        InputStream inputStream = null;
        try {
            channelSftp.cd(remotePath);
            inputStream = channelSftp.get(remoteName);
        } catch (SftpException e) {
            logger.error("download exception : {}", e.getMessage());
        }
        return inputStream;
    }

    /**
     * 上传文件：先切换路径，如果文件夹不存在就创建
     *
     * @param channelSftp
     * @param remoteFile
     * @param inputStream
     * @return
     */
    public static boolean uploadFile(ChannelSftp channelSftp, String remoteFile, InputStream inputStream) {
        String remotePath = remoteFile.substring(0, remoteFile.lastIndexOf("/"));
        String remoteName = remoteFile.substring(remoteFile.lastIndexOf("/") + 1);

        try {
            //将绝对路径转换成相对路径
            String remoteDirs = remotePath.replace(channelSftp.pwd(), "");
            if (!changePath(channelSftp, remoteDirs)) {
                logger.error("changePath fail : {}", remotePath);
                return false;
            }
            logger.info("pwd:{}", channelSftp.pwd());
            channelSftp.put(inputStream, remoteName);
            logger.info("file name:{}", remoteName);
            return true;
        } catch (SftpException e) {
            e.printStackTrace();
            logger.error("upload exception : {}", e.getMessage());
            return false;
        }
    }


    /**
     * 判断文件夹是否存在
     *
     * @param channelSftp
     * @param remoteDir
     * @return
     */
    public static boolean dirExist(ChannelSftp channelSftp, String remoteDir) {
        SftpATTRS stat = null;
        try {
            stat = channelSftp.stat(remoteDir);
        } catch (SftpException e) {
            logger.error("dirExist : {}", e.getMessage());
        }
        if (stat == null) {
            return false;
        } else {
            return stat.isDir();
        }
    }

    /**
     * 判断文件是否存在
     *
     * @param channelSftp
     * @param remoteFile
     * @return
     */
    public static boolean fileExists(ChannelSftp channelSftp, String remoteFile) {
        String remotePath = remoteFile.substring(0, remoteFile.lastIndexOf("/"));
        String remoteName = remoteFile.substring(remoteFile.lastIndexOf("/") + 1);
        try {
            channelSftp.cd(remotePath);
            Vector vector = channelSftp.ls(remoteName);
            if (vector != null && vector.size() != 0) {
                return true;
            } else {
                return false;
            }
        } catch (SftpException e) {
            logger.error("fileExists exception : ", e.getMessage());
            return false;
        }

    }

    /**
     * 切换路径前会先判断文件夹是否存在，如果不存在就创建
     *
     * @param channelSftp
     * @param remotePath
     * @return
     */
    public static boolean changePath(ChannelSftp channelSftp, String remotePath) {
        try {
            String[] remoteDirs = remotePath.split("/");
            for (String remoteDir : remoteDirs) {
                //检查为空表示当前路径
                if ("".equals(remoteDir)) {
                    continue;
                }
                // 检查文件夹是否存在
                if (!dirExist(channelSftp, remoteDir)) {
                    channelSftp.mkdir(remoteDir);
                }
                channelSftp.cd(remoteDir);
            }
            return true;
        } catch (SftpException e) {
            logger.error("upload exception : ", e.getMessage());
            return false;
        }
    }


}
